package com.yufubao.service.service.management.authorization.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yufubao.framework.constant.RoleConstant;
import com.yufubao.framework.result.PageUtils;
import com.yufubao.framework.result.ResponseResult;
import com.yufubao.framework.util.CopyBean;
import com.yufubao.framework.util.page.Query;
import com.yufubao.model.dto.management.sys.ChangeStatusDto;
import com.yufubao.model.dto.management.sys.SaveRoleMenuDto;
import com.yufubao.model.dto.management.sys.UpdateRoleMenuDto;
import com.yufubao.model.pojo.management.authorization.RoleEntity;
import com.yufubao.model.pojo.management.authorization.RoleMenuEntity;
import com.yufubao.model.vo.management.sys.RoleMenuTreeselectVO;
import com.yufubao.model.vo.management.sys.SelectRoleByIdVO;
import com.yufubao.model.vo.management.sys.SelectRoleVO;
import com.yufubao.service.mapper.management.authorization.RoleDao;
import com.yufubao.service.service.management.authorization.MenuService;
import com.yufubao.service.service.management.authorization.RoleMenuService;
import com.yufubao.service.service.management.authorization.RoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.yufubao.framework.constant.SystemConstants.ADMIN;


@Service("roleService")
@Slf4j
public class RoleServiceImpl extends ServiceImpl<RoleDao, RoleEntity> implements RoleService {

    @Autowired
    private RoleMenuService roleMenuService;

    @Autowired
    private MenuService menuService;

    /**
     * 角色分页查询
     *
     * @param params
     * @return
     */
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        //角色名称
        String key = (String) params.get("key");
        //状态
        String status = (String) params.get("status");

        LambdaQueryWrapper<RoleEntity> wrapper = Wrappers.<RoleEntity>lambdaQuery()
                .like(StrUtil.isNotBlank(key), RoleEntity::getRoleName, key);

        if (StrUtil.isNotBlank(status)) {
            switch (status) {
                case RoleConstant.OPEN:
                    wrapper.eq(RoleEntity::getStatus, RoleConstant.OPEN);
                    break;
                case RoleConstant.STOP:
                    wrapper.eq(RoleEntity::getStatus, RoleConstant.STOP);
                    break;
                default:
                    break;
            }
        }

        IPage<RoleEntity> page = this.page(
                new Query<RoleEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    /**
     * 根据人员id查询角色信息
     *
     * @param managerId
     * @return
     */
    @Override
    public List<String> selectRoleKeyByManagerId(Long managerId) {
        //判断是否是admin 如果是返回集合中只需要有admin
        if (managerId == 1L) {
            List<String> roleKeys = new ArrayList<>();
            roleKeys.add(ADMIN);
            return roleKeys;
        }
        //否则查询用户所具有的角色信息
        return getBaseMapper().selectRoleKeyByManagerId(managerId);
    }

    /**
     * @param dto
     * @return com.yufubao.framework.result.ResponseResult
     * @description 修改状态
     * @author zhangyiheng
     * @date 2024/9/12 18:12
     */
    @Override
    @Transactional
    public ResponseResult changeStatusById(ChangeStatusDto dto) {
        LambdaUpdateWrapper<RoleEntity> wrapper = new LambdaUpdateWrapper<>();
        //修改状态
        wrapper.eq(RoleEntity::getId, dto.getId())
                .set(RoleEntity::getStatus, dto.getStatus());

        this.update(wrapper);

        return ResponseResult.ok();
    }

    /**
     * @param saveRoleMenuDto
     * @return com.yufubao.framework.result.ResponseResult
     * @description 新增角色
     * @author zhangyiheng
     * @date 2024/9/12 18:30
     */
    @Override
    @Transactional
    public ResponseResult saveRoleMenu(SaveRoleMenuDto saveRoleMenuDto) {
        RoleEntity role = CopyBean.copyBean(saveRoleMenuDto, RoleEntity.class);

        this.save(role);

        List<RoleMenuEntity> roleMenus = saveRoleMenuDto.getMenuIds()
                .stream()
                .map(new Function<Long, RoleMenuEntity>() {
                    @Override
                    public RoleMenuEntity apply(Long menuId) {
                        RoleMenuEntity roleMenu = new RoleMenuEntity();
                        roleMenu.setMenuId(menuId);
                        roleMenu.setRoleId(role.getId());
                        return roleMenu;
                    }
                }).collect(Collectors.toList());

        roleMenuService.saveBatch(roleMenus);

        return ResponseResult.ok();
    }


    /**
     * @param id
     * @return com.yufubao.framework.result.ResponseResult<com.yufubao.model.vo.management.sys.SelectRoleByIdVO>
     * @description 修改角色回显
     * @author zhangyiheng
     * @date 2024/9/12 19:08
     */
    @Override
    public ResponseResult selectRoleById(Long id) {
        RoleEntity role = this.getById(id);
        SelectRoleByIdVO selectRoleByIdVO = CopyBean.copyBean(role, SelectRoleByIdVO.class);

        RoleMenuTreeselectVO roleMenuTreeselectVO = menuService.roleMenuTreeselect(id);
        selectRoleByIdVO.setCheckedKeys(roleMenuTreeselectVO.getCheckedKeys());
        selectRoleByIdVO.setMenus(roleMenuTreeselectVO.getMenus());

        return ResponseResult.okResult(selectRoleByIdVO);
    }


    /**
     * @param updateRoleMenuDto
     * @return com.yufubao.framework.result.ResponseResult
     * @description 修改角色
     * @author zhangyiheng
     * @date 2024/9/12 19:25
     */
    @Override
    @Transactional
    public ResponseResult updateRole(UpdateRoleMenuDto updateRoleMenuDto) {

        //先删 角色对应的权限中间表id对应数据
        if (updateRoleMenuDto.getId() != null) {
            LambdaQueryWrapper<RoleMenuEntity> wrapperr = new LambdaQueryWrapper<>();
            wrapperr.eq(RoleMenuEntity::getRoleId, updateRoleMenuDto.getId());
            roleMenuService.remove(wrapperr);
        }


        try {
            RoleEntity role = CopyBean.copyBean(updateRoleMenuDto, RoleEntity.class);

            this.updateById(role);

            //插入中间表数据
            List<RoleMenuEntity> roleMenuIdList = updateRoleMenuDto.getMenuIds()
                    .stream()
                    .map(new Function<Long, RoleMenuEntity>() {
                        @Override
                        public RoleMenuEntity apply(Long menuId) {
                            RoleMenuEntity roleMenu = new RoleMenuEntity();
                            roleMenu.setMenuId(menuId);
                            roleMenu.setRoleId(updateRoleMenuDto.getId());
                            return roleMenu;
                        }
                    }).collect(Collectors.toList());
            roleMenuService.saveBatch(roleMenuIdList);
            log.info("角色信息修改成功");
        } catch (Exception e) {
            log.error("角色数据修改失败 {}", e);
        }

        //返回状态
        return ResponseResult.ok();
    }

    /**
     * @param ids
     * @return com.yufubao.framework.result.ResponseResult
     * @description 批量删除
     * @author zhangyiheng
     * @date 2024/9/12 19:29
     */
    @Override
    @Transactional
    public ResponseResult deleteRoleByIds(Long[] ids) {
        this.removeByIds(Arrays.asList(ids));
        return ResponseResult.ok();
    }

    /**
     * @return com.yufubao.framework.result.ResponseResult<com.yufubao.model.vo.management.sys.SelectUserVO>
     * @description 查询角色列表接口
     * @author zhangyiheng
     * @date 2024/9/12 19:38
     */
    @Override
    public ResponseResult listAllRole() {
        List<RoleEntity> list = this.list(Wrappers.<RoleEntity>lambdaQuery()
                .eq(RoleEntity::getStatus, RoleConstant.OPEN));
        List<SelectRoleVO> copied = CopyBean.copyBeanList(list, SelectRoleVO.class);
        return ResponseResult.okResult(copied);
    }
}